home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / More Classes / Window Classes / ZScroller.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-14  |  20.2 KB  |  843 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp        -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZScroller.cpp        -- a window with scrollbars
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZScroller.h"
  23. #include    "MacZoop.h"
  24.  
  25.  
  26. static pascal void     ScrollBarZProc( ControlHandle theControl, short partCode );
  27. static pascal void    ThumbZProc();
  28.  
  29. static ControlActionUPP        gScrollbarProc = NewControlActionProc( ScrollBarZProc );
  30. static ThumbActionUPP        gThumbProc = NewThumbActionProc( ThumbZProc );
  31. static ControlHandle        gCurrentScrollbar = NULL;
  32.  
  33. /*--------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  34.  
  35. ZScroller::ZScroller(    ZCommander* aBoss,
  36.                         const short windID,
  37.                         const Boolean hasHScroll,
  38.                         const Boolean hasVScroll )
  39.     : ZDragDropWindow( aBoss, windID )
  40. {
  41.     theHBar = NULL;
  42.     theVBar = NULL;
  43.     SetRect( &bounds, 0, 0, 0, 0 );
  44.     hScale = 1;
  45.     vScale = 1;
  46.     
  47.     hasHBar = hasHScroll;
  48.     hasVBar = hasVScroll;
  49.     
  50.     cInitValue = 0;
  51. }
  52.  
  53.  
  54. /*--------------------------------***  INITZWINDOW  ***---------------------------------*/
  55. /*    
  56.  
  57. overrides the base ZWindow to initialise the scrollbars as well
  58.  
  59. ----------------------------------------------------------------------------------------*/
  60.  
  61. void    ZScroller::InitZWindow()
  62. {
  63.     inherited::InitZWindow();        // do the basic initialisation
  64.     
  65.     MakeScrollbars();                // make the scrollbar controls
  66. }
  67.  
  68.  
  69.  
  70. /*----------------------------------***  ACTIVATE  ***----------------------------------*/
  71. /*    
  72.  
  73. overrides ZWindow to show the scrollbars when the window state changes
  74.  
  75. ----------------------------------------------------------------------------------------*/
  76.  
  77. void    ZScroller::Activate()
  78. {
  79.     inherited::Activate();
  80.  
  81.     if ( hasVBar )
  82.         ShowControl( theVBar );
  83.         
  84.     if ( hasHBar )
  85.         ShowControl( theHBar );
  86. }
  87.  
  88.  
  89. /*---------------------------------***  DEACTIVATE  ***---------------------------------*/
  90. /*    
  91.  
  92. overrides ZWindow to hide the scrollbars when the window state changes
  93.  
  94. ----------------------------------------------------------------------------------------*/
  95.  
  96.  
  97. void    ZScroller::Deactivate()
  98. {
  99.     if ( hasVBar )
  100.         HideControl( theVBar );
  101.         
  102.     if ( hasHBar )
  103.         HideControl( theHBar );
  104.         
  105.     inherited::Deactivate();
  106. }
  107.  
  108.  
  109.  
  110. /*------------------------------------***  DRAW  ***------------------------------------*/
  111. /*    
  112.  
  113. overrides ZWindow to draw the content allowing for the scroll and the scrollbars themselves
  114.  
  115. ----------------------------------------------------------------------------------------*/
  116.  
  117. void    ZScroller::Draw()
  118. {
  119.     // need to set the origin to the scroll position here
  120.     
  121.     Rect    content;
  122.     short    fH, fV;
  123.     
  124.     GetContentRect( &content );
  125.     SetOriginToScroll();
  126.     
  127.     GetPosition( &fH, &fV );
  128.     OffsetRect( &content, fH, fV );
  129.     ClipRect( &content );
  130.  
  131.     DrawContent();
  132.     
  133.     SetOrigin( 0, 0 );
  134.     ClipRect( &macWindow->portRect );        
  135.     UpdateControls( macWindow, macWindow->visRgn );
  136.     
  137.     DrawGrow();
  138. }
  139.  
  140.  
  141. /*----------------------------------***  DRAWGROW  ***----------------------------------*/
  142. /*    
  143.  
  144. overrides ZWindow to draw the grow box, allowing for the actual scrollbars present
  145.  
  146. ----------------------------------------------------------------------------------------*/
  147.  
  148.  
  149. void    ZScroller::DrawGrow()
  150. {
  151.     // overrides the standard method to clip down to the growbox. This prevents
  152.     // scrollbar lines being drawn when there are no scrollbars in one dimension
  153.  
  154.     Rect    growBoxRect = macWindow->portRect;
  155.     
  156.     if (! hasVBar )
  157.         growBoxRect.top = growBoxRect.bottom - kStdScrollbarWidth;
  158.         
  159.     if (! hasHBar )
  160.         growBoxRect.left = growBoxRect.right - kStdScrollbarWidth;
  161.         
  162.     ClipRect( &growBoxRect );
  163.     DrawGrowIcon( macWindow );
  164. }
  165.  
  166.  
  167.  
  168. /*------------------------------------***  CLICK  ***-----------------------------------*/
  169. /*    
  170.  
  171. overrides ZWindow to handle clicks in the scrollbars and perform the scrolling
  172.  
  173. ----------------------------------------------------------------------------------------*/
  174.  
  175. void    ZScroller::Click( const Point mouse, const short modifiers )
  176. {
  177.     // handle a click in the content and also the scrollbar clicks
  178.     
  179.     short            partCode,curValue;
  180.     ControlHandle    hitCtl;
  181.     Point            soMouse = mouse;
  182.     
  183.     // did the mouse go down in any part of a control (scrollbar)?
  184.     
  185.     partCode = FindControl( mouse, macWindow, &hitCtl );
  186.     
  187.     if ( partCode == kControlNoPart )
  188.     {
  189.         // translate the point to the current scroll offset
  190.         // before passing it to ClickContent.
  191.         
  192.         if ( hasHBar )
  193.             soMouse.h += GetControlValue( theHBar );
  194.             
  195.         if ( hasVBar )
  196.             soMouse.v += GetControlValue( theVBar );
  197.         
  198.         ClickContent( soMouse, modifiers );
  199.     }
  200.     else
  201.     {
  202.         // scrollbar was hit, so track the control
  203.         
  204.         gCurrentScrollbar = hitCtl;
  205.         
  206.         curValue = GetControlValue( hitCtl );
  207.         
  208.         if ( partCode == kControlIndicatorPart )
  209.         {
  210.             #ifdef _LIVE_SCROLLING
  211.             cInitValue = GetControlValue( hitCtl );
  212.             partCode = TrackControl( hitCtl, mouse, gThumbProc );
  213.             #else
  214.             partCode = TrackControl( hitCtl, mouse, NULL );
  215.             #endif
  216.         }
  217.         else
  218.             partCode = TrackControl( hitCtl, mouse, gScrollbarProc );
  219.         
  220.         // if the thumb was dragged, figure out where it was dragged to and scroll
  221.         // the contents appropriately
  222.         
  223.         if ( partCode == kControlIndicatorPart )
  224.         {
  225.             #ifndef _LIVE_SCROLLING
  226.             curValue -= GetControlValue( hitCtl );
  227.             
  228.             if ( hitCtl == theHBar )
  229.                 Scroll( curValue, 0 );
  230.             else
  231.                 Scroll( 0, curValue );
  232.             #endif
  233.  
  234.             PostScroll( hitCtl );
  235.         }
  236.         gCurrentScrollbar = NULL;
  237.     }
  238. }
  239.  
  240.  
  241. /*-------------------------------***  CLICKCONTENT  ***---------------------------------*/
  242. /*    
  243.  
  244. You can override this to handle clicks in the content area of the window
  245.  
  246. ----------------------------------------------------------------------------------------*/
  247.  
  248.  
  249. void    ZScroller::ClickContent( const Point mouse, const short modifiers )
  250. {
  251. }
  252.  
  253. /*-----------------------------------***  SETSIZE  ***----------------------------------*/
  254. /*    
  255.  
  256. overrides ZWindow to reposition the scrollbars when the window size is changed
  257.  
  258. ----------------------------------------------------------------------------------------*/
  259.  
  260. void    ZScroller::SetSize( const short width, const short height, const Boolean reDraw )
  261. {
  262.     Focus();
  263.     
  264.     if ( hasVBar )
  265.         HideControl( theVBar );
  266.         
  267.     if ( hasHBar )
  268.         HideControl( theHBar );
  269.         
  270.     // need to erase the grow icon before sizing
  271.     
  272.     Rect    growRect = macWindow->portRect;
  273.     
  274.     growRect.left = growRect.right - kStdScrollbarWidth;
  275.     growRect.top = growRect.bottom - kStdScrollbarWidth;
  276.     EraseRect( &growRect );
  277.     InvalRect( &growRect );
  278.     
  279.     inherited::SetSize( width, height, reDraw );
  280.     
  281.     MoveScrollbars();
  282.     
  283.     if ( reDraw )
  284.         Draw();
  285. }
  286.  
  287.  
  288.  
  289. /*------------------------------------***  ZOOM  ***------------------------------------*/
  290. /*    
  291.  
  292. overrides ZWindow to reposition the scrollbars when the window is zoomed
  293.  
  294. ----------------------------------------------------------------------------------------*/
  295.  
  296. void    ZScroller::Zoom( const short partCode )
  297. {
  298.     if ( hasVBar )
  299.         HideControl( theVBar );
  300.         
  301.     if ( hasHBar )
  302.         HideControl( theHBar );
  303.     
  304.     inherited::Zoom( partCode );
  305.  
  306.     MoveScrollbars();
  307.     Draw();
  308.     ValidRect( &macWindow->portRect );
  309. }
  310.  
  311.  
  312. /*----------------------------------***  SETBOUNDS  ***---------------------------------*/
  313. /*    
  314.  
  315. sets the scrollable area to a certain size. This then recalculates the scrollbar settings
  316. so that that area can be scrolled over. The bounds is the "real" size of a document.
  317.  
  318. ----------------------------------------------------------------------------------------*/
  319.  
  320.  
  321. void    ZScroller::SetBounds( const Rect& aBounds)
  322. {
  323.     bounds = aBounds;
  324.     CalculateControlParams();
  325.     
  326.     // by default, set the sizeRect for the window to the bounds
  327.     // plus the scrollbar widths
  328.     
  329.     Rect    sz = aBounds;
  330.     
  331.     sz.top = sizeRect.top;
  332.     sz.left = sizeRect.left;
  333.     
  334.     if ( hasHBar )
  335.         sz.bottom += kStdScrollbarWidth;
  336.         
  337.     if ( hasVBar )
  338.         sz.right += kStdScrollbarWidth;
  339.     
  340.     SetSizeRect( sz );
  341. }
  342.  
  343.  
  344.  
  345. /*---------------------------------***  GETBOUNDS  ***----------------------------------*/
  346. /*    
  347.  
  348. get the scrollable area
  349.  
  350. ----------------------------------------------------------------------------------------*/
  351.  
  352. void    ZScroller::GetBounds( Rect* aBounds )
  353. {
  354.     *aBounds = bounds;
  355. }
  356.  
  357.  
  358.  
  359. /*------------------------------***  SETSCROLLAMOUNT  ***-------------------------------*/
  360. /*    
  361.  
  362. sets how many pixels each click on a scroll arrow shifts the content area
  363.  
  364. ----------------------------------------------------------------------------------------*/
  365.  
  366. void    ZScroller::SetScrollAmount( const short hAmount, const short vAmount )
  367. {
  368.     hScale = hAmount;
  369.     vScale = vAmount;
  370. }
  371.  
  372.  
  373. /*--------------------------------***  GETPOSITION  ***---------------------------------*/
  374. /*    
  375.  
  376. returns the current scroll position of the window- i.e. the "frame" position relative to
  377. the "real" document area (the bounds)
  378.  
  379. ----------------------------------------------------------------------------------------*/
  380.  
  381.  
  382. void    ZScroller::GetPosition( short* hPosition, short* vPosition )
  383. {
  384.     if ( hasVBar )
  385.         *vPosition = GetControlValue( theVBar );
  386.     else
  387.         *vPosition = 0;
  388.         
  389.     if ( hasHBar )
  390.         *hPosition = GetControlValue( theHBar );
  391.     else
  392.         *hPosition = 0;
  393. }
  394.  
  395.  
  396.  
  397. /*----------------------------------***  SCROLLTO  ***----------------------------------*/
  398. /*    
  399.  
  400. moves the content area to the scroll position passed. This immediately redraws the content
  401.  
  402. ----------------------------------------------------------------------------------------*/
  403.  
  404. void    ZScroller::ScrollTo( const short hPosition, const short vPosition )
  405. {
  406.     Focus();
  407.     
  408.     if ( hasHBar )
  409.         SetControlValue( theHBar, hPosition );
  410.         
  411.     if ( hasVBar )
  412.         SetControlValue( theVBar, vPosition );
  413.         
  414.     Draw();
  415. }
  416.  
  417.  
  418.  
  419. /*-------------------------------***  GETCONTENTRECT  ***-------------------------------*/
  420. /*    
  421.  
  422. get the scrollable portion of the window- the bit you can see, less the scrollbars.
  423.  
  424. ----------------------------------------------------------------------------------------*/
  425.  
  426. void    ZScroller::GetContentRect( Rect* aRect )
  427. {
  428.     // returns the scrollable part of the window. The bit without the scrollbars.
  429.  
  430.     *aRect = macWindow->portRect;
  431.     if ( hasVBar )
  432.         aRect->right -= kStdScrollbarWidth;
  433.         
  434.     if ( hasHBar )
  435.         aRect->bottom -= kStdScrollbarWidth;
  436. }
  437.  
  438.  
  439.  
  440. /*---------------------------***  CALCULATECONTROLPARAMS  ***---------------------------*/
  441. /*    
  442.  
  443. sets the scrollbar maximums to correctly scroll the scrollarea. This is called when the
  444. bounds or the window frame area changes.
  445.  
  446. ----------------------------------------------------------------------------------------*/
  447.  
  448. void    ZScroller::CalculateControlParams()
  449. {
  450.     // this sets the maximums of the scrollbar to the difference between the content rect and
  451.     // the bounds.
  452.     
  453.     Rect    content;
  454.     short    hMax,vMax;
  455.     
  456.     GetContentRect( &content );
  457.     
  458.     hMax = ( bounds.right - bounds.left ) - ( content.right - content.left );
  459.     vMax = ( bounds.bottom - bounds.top ) - ( content.bottom - content.top );
  460.     
  461.     if ( hMax < 0 )
  462.         hMax = 0;
  463.         
  464.     if ( vMax < 0 )
  465.         vMax = 0;
  466.         
  467.     if ( hasHBar )
  468.         SetControlMaximum( theHBar, hMax );
  469.         
  470.     if ( hasVBar )
  471.         SetControlMaximum( theVBar, vMax );
  472. }
  473.  
  474.  
  475.  
  476. /*-------------------------------***  MAKESCROLLBARS  ***-------------------------------*/
  477. /*    
  478.  
  479. creates the scrollbars as part of the initialisation
  480.  
  481. ----------------------------------------------------------------------------------------*/
  482.  
  483. void    ZScroller::MakeScrollbars()
  484. {
  485.     // create the scrollbar controls initially. This is done by calling NewControl. We
  486.     // figure out the control rects from the window portrect.
  487.     
  488.     Rect    barRect;
  489.     Rect    wPortRect;
  490.     
  491.     wPortRect = macWindow->portRect;
  492.     
  493.     if ( hasHBar )
  494.     {
  495.         barRect = wPortRect;
  496.         barRect.right -= kStdScrollbarWidth - 1;
  497.         barRect.top = barRect.bottom - kStdScrollbarWidth - 1;
  498.         barRect.left -= 1;
  499.         OffsetRect(&barRect,0,1);
  500.         
  501.         FailNIL( theHBar = NewControl( macWindow, &barRect, NULL, FALSE, 0, 0, 0, scrollBarProc, (long) this));
  502.     
  503.         SetControlReference( theHBar, (long) this );
  504.     }
  505.     
  506.     if ( hasVBar )
  507.     {
  508.         barRect = wPortRect;
  509.         barRect.bottom -= kStdScrollbarWidth - 1;
  510.         barRect.left = barRect.right - kStdScrollbarWidth - 1;
  511.         barRect.top -= 1;
  512.         OffsetRect( &barRect, 1, 0 );
  513.  
  514.         FailNIL(theVBar = NewControl( macWindow, &barRect, NULL, FALSE, 0, 0, 0, scrollBarProc, (long) this));
  515.         
  516.         SetControlReference( theVBar, (long) this );
  517.     }
  518. }
  519.  
  520.  
  521.  
  522. /*-------------------------------***  MOVESCROLLBARS  ***-------------------------------*/
  523. /*    
  524.  
  525. moves the scrollbars to the edges of the window. Called when the window frame size changes.
  526. The scrollbars should generally be hidden before this operation. This then reshows them if
  527. the window is active, and recomputes the max values. If the scroll position is forced to
  528. change as a result, this redraws the content in the correct position.
  529.  
  530. ----------------------------------------------------------------------------------------*/
  531.  
  532. void    ZScroller::MoveScrollbars()
  533. {
  534.     // move the scrollbars after the window size has changed. They should be hidden beforehand
  535.     // and then shown afterwards. This will only show them if the window is active.
  536.     
  537.     Rect        wPortRect;
  538.     short        w,h,hVal = 0,vVal = 0;
  539.     Boolean        isActive;
  540.     
  541.     wPortRect = macWindow->portRect;
  542.     isActive = IsWindowHilited( macWindow );    // using Copland type macro
  543.     
  544.     if ( hasHBar )
  545.     {
  546.         hVal = GetControlValue( theHBar );
  547.  
  548.         w = wPortRect.right - wPortRect.left - kStdScrollbarWidth + 2;
  549.         h = kStdScrollbarWidth + 1;
  550.         
  551.         SizeControl( theHBar, w, h );
  552.         MoveControl( theHBar, wPortRect.left - 1, wPortRect.bottom - kStdScrollbarWidth );
  553.         
  554.         if ( isActive )
  555.             ShowControl( theHBar );
  556.         
  557.         ValidRect(&(*theHBar)->contrlRect);
  558.     }
  559.     
  560.     if ( hasVBar )
  561.     {
  562.         vVal = GetControlValue( theVBar );
  563.         
  564.         h = wPortRect.bottom - wPortRect.top - kStdScrollbarWidth + 2;
  565.         w = kStdScrollbarWidth + 1;
  566.         
  567.         SizeControl(theVBar, w, h );
  568.         MoveControl(theVBar, wPortRect.right - kStdScrollbarWidth,  wPortRect.top - 1 );
  569.         
  570.         if ( isActive )
  571.             ShowControl( theVBar );
  572.             
  573.         ValidRect(&(*theVBar)->contrlRect);
  574.     }
  575.     
  576.     CalculateControlParams();    // recompute maximums
  577.     
  578.     if ( hasVBar )
  579.         vVal -= GetControlValue( theVBar );
  580.         
  581.     if ( hasHBar )
  582.         hVal -= GetControlValue( theHBar );
  583.     
  584.     // if the value of the control changed as a result of altering the maximum, we need to
  585.     // ensure that the contents are scrolled to the right place.
  586.         
  587.     if ( hVal || vVal )
  588.     {
  589.         GetContentRect( &wPortRect );
  590.         EraseRect( &wPortRect );
  591.     }
  592. }
  593.  
  594.  
  595.  
  596. /*---------------------------------***  POSTSCROLL  ***---------------------------------*/
  597. /*    
  598.  
  599. You can override this if you are interested in getting called after the thumb of a
  600. scrollbar was dragged.
  601.  
  602. ----------------------------------------------------------------------------------------*/
  603.  
  604. void    ZScroller::PostScroll( ControlHandle aCtl )
  605. {
  606. }
  607.  
  608.  
  609. /*------------------------------------***  SCROLL  ***----------------------------------*/
  610. /*    
  611.  
  612. shifts the content by dH and dV, updating the revealed area. This is called by the scroll
  613. bar callback function to implement continous scrolling.
  614.  
  615. ----------------------------------------------------------------------------------------*/
  616.  
  617. void    ZScroller::Scroll( const short dH, const short dV )
  618. {
  619.     // scrolls the content rect. This calls scrollrect to move the majority of the
  620.     // pixels, then calls DrawContent to fill in the rest.
  621.     
  622.     RgnHandle    updateRgn,saveClip;
  623.     Rect        content;
  624.     short        fH,fV;
  625.     
  626.     GetContentRect( &content );
  627.     updateRgn = NewRgn();
  628.     
  629.     GetClip( saveClip = NewRgn());
  630.     ScrollRect( &content, dH, dV, updateRgn );
  631.     
  632.     // need to set the origin of the view to the new location
  633.     
  634.     SetOriginToScroll();
  635.     
  636.     // offset the update region to allow for the origin
  637.     
  638.     GetPosition( &fH, &fV );
  639.     OffsetRgn( updateRgn, fH, fV );
  640.     SetClip( updateRgn );
  641.     
  642.     // draw the update region
  643.     
  644.     DrawContent();
  645.     
  646.     // restore the zero origin
  647.     
  648.     SetOrigin( 0, 0 );
  649.     SetClip( saveClip );
  650.     
  651.     DisposeRgn( saveClip );
  652.     DisposeRgn( updateRgn );
  653. }
  654.  
  655.  
  656. /*-----------------------------***  SETORIGINTOSCROLL  ***------------------------------*/
  657. /*    
  658.  
  659. sets the origin of the grafport to the correct scroll position. This is done to ensure
  660. that the contents get drawn in the right place regardless of where they are scrolled to.
  661.  
  662. ----------------------------------------------------------------------------------------*/
  663.  
  664. void    ZScroller::SetOriginToScroll()
  665. {
  666.     short vOrigin = 0;
  667.     short hOrigin = 0;
  668.     
  669.     if ( hasVBar )
  670.         vOrigin = GetControlValue( theVBar );
  671.         
  672.     if ( hasHBar )
  673.         hOrigin = GetControlValue( theHBar );
  674.         
  675.     SetOrigin( hOrigin, vOrigin );
  676. }
  677.  
  678.  
  679. /*-------------------------------***  SCROLLHANDLER  ***--------------------------------*/
  680. /*    
  681.  
  682. scrollbar callback function actually changes the scrollbar value as scrolling progresses
  683. and scrolls the content accordingly.
  684.  
  685. ----------------------------------------------------------------------------------------*/
  686.  
  687. void    ZScroller::ScrollHandler( const ControlHandle aCtl, const short partCode )
  688. {
  689.     // this actually peforms the scroll of the content rect
  690.     
  691.     short        curValue,page;
  692.     Boolean        hitIsVertical;
  693.     Rect        content;
  694.     
  695.     curValue = GetControlValue( aCtl );
  696.     
  697.     // are we scrolling the horizontal or the vertical bar? Find out by comparing
  698.     // the control with one of our data members
  699.     
  700.     hitIsVertical = ( aCtl == theVBar );
  701.     
  702.     // calculate the page amount. This is the height or width of the window less one
  703.     // scale amount.
  704.         
  705.     GetContentRect( &content );
  706.     
  707.     if ( hitIsVertical )
  708.         page = content.bottom - content.top - vScale;
  709.     else
  710.         page = content.right - content.left - hScale;     
  711.     
  712.     switch ( partCode )
  713.     {
  714.         case kControlUpButtonPart:
  715.             SetControlValue( aCtl, GetControlValue(aCtl) - (hitIsVertical? vScale : hScale ));
  716.             break;
  717.         case kControlDownButtonPart:
  718.             SetControlValue( aCtl, GetControlValue(aCtl) + (hitIsVertical? vScale : hScale ));
  719.             break;
  720.         case kControlPageUpPart:
  721.             SetControlValue( aCtl, GetControlValue(aCtl) - page );
  722.             break;
  723.         case kControlPageDownPart:
  724.             SetControlValue( aCtl, GetControlValue(aCtl) + page );
  725.             break;
  726.         case kControlIndicatorPart:
  727.             // called when live scrolling the thumb. Here we need to calculate where the mouse
  728.             // is and figure out what the correct control value would be. If the mouse goes outside the
  729.             // control too far, the control "springs back" to its previous value, stored in cInitValue.
  730.             // we have to keep control here until the mouse is released otherwise the alterations to
  731.             // the control value cause problems for the thumb dragging default behaviour if we allow
  732.             // control back every time we are called. Yet another annoying toolbox anomaly...
  733.             
  734.             #ifdef _LIVE_SCROLLING
  735.             
  736.             Rect    cr, slopR;
  737.             long    cRange, cVal;
  738.             Point    curMouse, lastMouse;
  739.             
  740.             GetMouse( &lastMouse );
  741.             
  742.             cr = (*aCtl)->contrlRect;
  743.             slopR = cr;
  744.             InsetRect( &slopR, -20, -20 );
  745.             
  746.             if ( hitIsVertical )
  747.             {
  748.                 cr.top += kWidthOfScrollArrow;
  749.                 cr.bottom -= kWidthOfScrollArrow;
  750.             }
  751.             else
  752.             {
  753.                 cr.left += kWidthOfScrollArrow;
  754.                 cr.right -= kWidthOfScrollArrow;
  755.             }
  756.             
  757.             cRange = GetControlMaximum( aCtl ) - GetControlMinimum( aCtl );
  758.             
  759.             while ( StillDown())
  760.             {
  761.                 GetMouse( &curMouse );
  762.                 
  763.                 if ( DeltaPoint( curMouse, lastMouse ))
  764.                 {
  765.                     lastMouse = curMouse;
  766.                     
  767.                     // calculate value based on mouse location
  768.                     
  769.                     if ( PtInRect( curMouse, &slopR ))
  770.                     {
  771.                         if ( hitIsVertical )
  772.                             cVal = ((long)( curMouse.v - cr.top ) * cRange ) / (long)( cr.bottom - cr.top );
  773.                         else
  774.                             cVal = ((long)( curMouse.h - cr.left ) * cRange ) / (long)( cr.right - cr.left );
  775.                         
  776.                         SetControlValue( aCtl, cVal );
  777.                     }
  778.                     else
  779.                         SetControlValue( aCtl, cInitValue );        // "spring" back...
  780.                         
  781.                     curValue -= GetControlValue( aCtl );
  782.                     
  783.                     if ( hitIsVertical )
  784.                         Scroll( 0, curValue );
  785.                     else
  786.                         Scroll( curValue, 0 );
  787.                         
  788.                     curValue = GetControlValue( aCtl );
  789.                 }
  790.             }
  791.             
  792.             // the control manager will attempt to draw the thumb at this point. We'd rather it didn't
  793.             // since we've already moved it. Thus we empty the clip region. A hack, but it works...
  794.             
  795.             SetRect( &cr, 0, 0, 0, 0 );
  796.             ClipRect( &cr );
  797.             
  798.             #endif
  799.             break;
  800.     }
  801.     
  802.     if ( partCode != kControlIndicatorPart )
  803.     {
  804.         curValue -= GetControlValue( aCtl );
  805.         
  806.         if ( hitIsVertical )
  807.             Scroll( 0, curValue );
  808.         else
  809.             Scroll( curValue, 0 );
  810.     }
  811. }
  812.  
  813.  
  814.  
  815.  
  816. #pragma mark -
  817.  
  818.  
  819.  
  820. static pascal void    ScrollBarZProc( ControlHandle theControl, short partCode )
  821. {
  822.     // action proc for passing scrolling callbacks back to the object.
  823.     
  824.     ZScroller*    aScroller = (ZScroller*) GetControlReference( theControl );
  825.     
  826.     if ( aScroller )
  827.         aScroller->ScrollHandler( theControl, partCode );
  828. }
  829.  
  830.  
  831.  
  832. static pascal void    ThumbZProc()
  833. {
  834.     if ( gCurrentScrollbar )
  835.     {
  836.         ZScroller*    zs = ( ZScroller*) GetControlReference( gCurrentScrollbar );
  837.         
  838.         if ( zs )
  839.             zs->ScrollHandler( gCurrentScrollbar, kControlIndicatorPart );
  840.     }
  841. }
  842.  
  843.